﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;

namespace BattleThis.Core.Movement
{
	/// <summary>
	/// Descripte a path a unit can go.
	/// </summary>
	[System.Diagnostics.DebuggerDisplay( "Path Target-Position {Position} Remianing: {RemainingM} WayPoints: {WayPoints}" )]
	public class Path
	{

		#region Variablen
		public static readonly Path Close = new Path();

		private SortedList<int, Position> m_WayPoints = new SortedList<int, Position>();
		private ActionPoint m_RemainingMovment = ActionPoint.Empty;
		#endregion

		#region Properties
		/// <summary>
		/// Gets the way points of the path.
		/// </summary>
		public IEnumerable<KeyValuePair<int, Position>> WayPoints
		{
			get { return m_WayPoints; }
		}

		/// <summary>
		/// Gets the target of this path.
		/// </summary>
		public Position Target
		{
			get { return m_WayPoints.Last().Value; }
		}

		/// <summary>
		/// Gets the remaining Action Points if a unit move this path.
		/// </summary>
		public ActionPoint Remaining
		{
			get { return m_RemainingMovment; }
		}
		#endregion

		#region Methoden
		/// <summary>
		/// Prevents a default instance of the <see cref="Path"/> class from being created.
		/// </summary>
		private Path()
		{
			m_WayPoints.Add( 0, Position.Undefined );
			m_RemainingMovment = ActionPoint.Empty;
		}

		/// <summary>
		/// Initializes a new instance of the <see cref="Path"/> class.
		/// </summary>
		/// <param name="target">The target.</param>
		/// <param name="remaining">The remaining action points.</param>
		public Path( Position target, ActionPoint remaining )
			: this( target, Enumerable.Empty<KeyValuePair<int, Position>>(), remaining )
		{ }

		/// <summary>
		/// Initializes a new instance of the <see cref="Path"/> class.
		/// </summary>
		/// <param name="target">The target.</param>
		/// <param name="orgin">The orgin.</param>
		/// <param name="remaining">The remaining action points.</param>
		public Path( Position target, Path orgin, ActionPoint remaining )
			: this( target, orgin.WayPoints, remaining )
		{ }

		/// <summary>
		/// Initializes a new instance of the <see cref="Path"/> class.
		/// </summary>
		/// <param name="target">The target.</param>
		/// <param name="wayPoints">The way points.</param>
		/// <param name="remaining">The remaining action points that were calulated.</param>
		public Path( Position target, IEnumerable<KeyValuePair<int, Position>> wayPoints, ActionPoint remaining )
		{
			if( target == null ) throw new ArgumentNullException( "target" );
			if( wayPoints == null ) throw new ArgumentNullException( "wayPoints" );
			if( remaining == null ) throw new ArgumentNullException( "remaining" );
			if( target.IsUndefined() ) throw new ArgumentOutOfRangeException( "target" );

			foreach( var item in wayPoints )
			{
				m_WayPoints.Add( item.Key, item.Value );
			}

			var counter =  wayPoints.Count() == 0 ?  0 : wayPoints.Last().Key + 1;

			m_WayPoints.Add( counter, target );
			m_RemainingMovment = remaining;
		}

		/// <summary>
		/// Determines whether [is cheaper as] [the specified to compare].
		/// </summary>
		/// <param name="toCompare">To compare.</param>
		/// <returns>
		///   <c>true</c> if [is cheaper as] [the specified to compare]; otherwise, <c>false</c>.
		/// </returns>
		public bool IsCheaperAs( Path toCompare )
		{
			if( toCompare == null ) throw new ArgumentNullException( "toCompare" );

			return this.Remaining.Remaining >= toCompare.Remaining.Remaining;
		}
		#endregion

	}
}